# 以为本机使用VSCode 在运行时会有一些多余的信息,分割代码和无用信息
print('--' * 30)
#!  1. 数据处理

# 导入需要用到的包文件,在本地运行需要安装numpy  as:别名
import numpy as np
import json


#> 5. 封装load_data函数
def load_data():
    #> 1.导入数据
    #? 读入文件数据到变量中
    datafile = './housing.data'
    # 根据路径,读取数据,以空格为间隔, 返回值为数组(列表)
    data = np.fromfile(datafile, sep=' ')
    # print(len(data))
    #> 2. 数据格式调整

    # 根据图像,有十四个特征数据,通过将每个特殊数据保存,获得数据长度.
    feature_names = [
        'CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX',
        'PTRATIO', 'B', 'LSTAT', 'MEDV'
    ]
    # 获取字段数据长度
    feature_num = len(feature_names)
    """
      data.shape[0] 获得数据量 7084
      // 是整数除法 data.shape[0] // feature_num = 7084 ÷ 14 = 506
      data.reshape 将data中的数据变成一个(506 *14)的矩阵
    """
    # data.reshape按照指定数组将数据变为一个数据矩阵 506 ,14
    data = data.reshape([data.shape[0] // feature_num, feature_num])
    # print(data)
    #> 3.数据集划分
    # 预置80%数据做训练集
    ratio = 0.8
    # 506* 0.8 得出一个偏移量,并强转为整形数字
    offset = int(data.shape[0] * ratio)
    # python语法:分片; 截取数据的80% 为训练集数据,并使用新的变量保存
    training_data = data[:offset]
    # training_data.shape 打印得出数据为404 *14的数据矩阵

    #> 4.数据归一化
    # 获取train数据集 每列的最大值
    maximums = training_data.max(axis=0)
    # 获取train数据集 每列最小值
    minimums = training_data.min(axis=0)
    #! 获取train数据集 平均值 下面的代码改过,所以之类获取后并没有使用
    avgs = training_data.sum(axis=0) / training_data.shape[0]
    # print(maximums)
    # print(minimums)
    # print(avgs)
    # 对数据进行归一化处理:
    for i in range(feature_num):
        #! 这里是总数据的做的处理,不是训练数据, 整个公式的意义还没有理解
        # 数组中的第i值进行运算 
        data[:, i] = (data[:, i] - minimums[i]) / (maximums[i] - minimums[i])
    
    # 训练集数据
    training_data = data[:offset]
    # 测试集数据
    test_data = data[offset:]
    #? 根据python的特性,返回值是多个.本质上利用元组语法的特性
    return training_data, test_data


# 获取数据
training_data, test_data = load_data()
x = training_data[:, :-1]
y = training_data[:, -1:]

#! 2.模型设计
class Network(object):
    def __init__(self, num_of_weights):
        # 随机产生w的初始值
        # 为了保持程序每次运行结果的一致性，此处设置固定的随机数种子
        np.random.seed(0)
        self.w = np.random.randn(num_of_weights, 1)
        self.b = 0.

    def forward(self, x):
        z = np.dot(x, self.w) + self.b
        return z

    def loss(self, z, y):
        error = z - y
        cost = error * error
        cost = np.mean(cost)
        return cost


net = Network(13)
# 此处可以一次性计算多个样本的预测值和损失函数
x1 = x[0:3]
y1 = y[0:3]
z = net.forward(x1)
print('predict: ', z)
loss = net.loss(z, y1)
print('loss:', loss)